package model

import (
	"time"
	"tools-api/src/common/db/database"

	"xorm.io/xorm"
)

// BookDetail 明细
type BookDetail struct {
	Id         int64     `json:"id"`
	Uuid       string    `json:"-"`
	BookId     int64     `json:"book_id"`
	AccountsId int64     `json:"accounts_id"` // 收支账户
	TypesId    int64     `json:"types_id"`
	Type       int       `json:"type"` // 1:支出 2:收入
	Money      float64   `json:"money"`
	Date       string    `json:"date"`
	Remark     string    `json:"remark"`
	CreatedAt  time.Time `xorm:"created" json:"-"`
	ModifiedAt time.Time `xorm:"updated" json:"-"`
	DeleteMark int       `xorm:"delete_mark" json:"-"`
}
type BookDetailResult struct {
	BookDetail  `xorm:"extends"`
	TypesKey    string `json:"types_key"`
	TypesName   string `json:"types_name"`
	AccountId   int64  `json:"account_id"` // 收支账户
	AccountIcon string `json:"account_icon"`
	Account     string `json:"account"`
}

// BookAccountsResult 返回结果
type BookAccountsResult struct { // 返回结果
	Id         int64  `json:"id"`
	Key        string `json:"key"`
	Name       string `json:"name"`
	MonthStart int    `json:"month_start"`
	Def        bool   `json:"def" xorm:"tinyint(1)"`
	Sort       int    `json:"sort"`
	Count      int    `json:"-"` // 只有大于0 等于0
	NotZero    bool   `json:"not_zero" xorm:"tinyint(1)"`
}

var DefBookAccount = BookAccountsResult{ // 缺省默认账户
	Id:         0,
	Key:        "qita",
	Name:       "不计入账户",
	MonthStart: 1,
	Def:        false,
	Sort:       0,
}

func (detail BookDetail) Create() BookDetail {
	_, _ = database.JCJEngine.Insert(&detail)
	return detail
}

func (detail BookDetail) Update() error {
	_, err := database.JCJEngine.Where("id=? and uuid=?", detail.Id, detail.Uuid).Update(&detail)
	return err
}

// GetListByUuid date 2025-07 某一个月份，后期可以考虑账单日
func (detail BookDetail) GetListByUuid(session *xorm.Session, uuid string, bookId, typesId int64, dateStart, dateEnd string) []BookDetailResult {
	list := make([]BookDetailResult, 0) // []string{"user_db.user", "u"}
	defAccount := DefBookAccount
	s := session.Table("book_detail").Alias("t").
		Select("t.id, t.book_id, t.type, t.money, t.date, t.remark, t.types_id, b.key as types_key, b.name as types_name,"+
			" t.accounts_id as account_id, case when a.name is null then '"+defAccount.Name+"' else a.name end as account,"+
			" case when a.key is null then '"+defAccount.Key+"' else a.key end as account_icon").
		Join("LEFT", []string{"book_types", "b"}, "b.id = t.types_id").
		Join("LEFT", []string{"book_accounts", "a"}, "a.id = t.accounts_id").
		Where("t.uuid=? and t.book_id=? and t.delete_mark=0 and t.date between ? and ?", uuid, bookId, dateStart, dateEnd)
	if typesId > 0 {
		s = s.Where("t.types_id=?", typesId)
	}
	_ = s.Desc("t.date", "t.id").Find(&list)
	return list
}

// GetSumMoney 周期内 收入/支出 合计金额
func (detail BookDetail) GetSumMoney(session *xorm.Session, uuid string, bookId int64, dateStart, dateEnd string) (float64, float64) {
	type res struct {
		Payout float64
		Income float64
	}
	r := res{}
	_, _ = session.Table(BookDetail{}).
		Select("sum(case when type = 1 then money else 0 end) as payout, sum(case when type = 2 then money else 0 end) as income").
		Where("uuid=? and book_id=? and delete_mark=0 and date between ? and ?", uuid, bookId, dateStart, dateEnd).
		Get(&r)
	return r.Payout, r.Income
}

// Delete 单个删除
func (detail BookDetail) Delete(uuid string, id int64) error {
	detail.DeleteMark = 1
	_, err := database.JCJEngine.Where("id=? and uuid=?", id, uuid).Update(&detail)
	if err != nil {
		return err
	}
	return nil
}

// DeleteDetailByAccounts 删除某个账户下的收支明细
func (detail BookDetail) DeleteDetailByAccounts(session *xorm.Session, uuid string, accountsId int64) error {
	_, err := session.Where("accounts_id=? and uuid=?", accountsId, uuid).Cols("delete_mark").Update(&BookDetail{DeleteMark: 1})
	return err
}

// DeleteDetailByBook 删除某个账本下的收支明细
func (detail BookDetail) DeleteDetailByBook(session *xorm.Session, uuid string, BookId int64) error {
	_, err := session.Where("book_id=? and uuid=?", BookId, uuid).Cols("delete_mark").Update(&BookDetail{DeleteMark: 1})
	return err
}

// DeleteDetailByTypes 删除某个类别下的收支明细
func (detail BookDetail) DeleteDetailByTypes(session *xorm.Session, uuid string, typesId int64) error {
	_, err := session.Where("types_id=? and uuid=?", typesId, uuid).Cols("delete_mark").Update(&BookDetail{DeleteMark: 1})
	return err
}

// TransformDetailByAccounts 收支明细 转移收支账户
func (detail BookDetail) TransformDetailByAccounts(session *xorm.Session, uuid string, fromAccountsId, toAccountsId int64) error {
	_, err := session.Where("accounts_id=? and uuid=?", fromAccountsId, uuid).Cols("accounts_id").Update(&BookDetail{AccountsId: toAccountsId})
	return err
}

// TransformDetailByTypes 收支明细 转移类别
// 要求类型相同
func (detail BookDetail) TransformDetailByTypes(session *xorm.Session, uuid string, fromTypesId, toTypesId int64) error {
	sql := "UPDATE book_detail t" +
		" INNER JOIN book_types r1 ON t.types_id = r1.id AND r1.id = ?" +
		" INNER JOIN book_types r2 ON r2.id = ? AND r1.type = r2.type" +
		" SET t.types_id = ? WHERE t.types_id=? and t.uuid=?"
	_, err := session.Exec(sql, fromTypesId, toTypesId, toTypesId, fromTypesId, uuid)
	return err
}
